#pragma once

#include "mccommonapi.h"

#include <string>
#include <fstream>
#include <WTypes.h>

namespace MCCommon
{

/**
 * Format log string.
 * 
 * Note: The usage of this function is like sprintf_s.
 *
 * Example: FormatString( "%d,%c", 10, 'a' );
 */ 
std::string MCAPI FormatString
(
    const char* format,
    ...
);

class MCAPI Logger
{
public:    
    // The log level.
    enum TraceLevel
    {
        // This level will be export always.
        kTL_Error = 0,

        // This level will be used to record warnings.
        kTL_Warning = 1,

        // This level will always be used to record the main work flow.        
        kTL_Info = 2,

        // This level will export all debug info, 
        // it may affect performance.
        kTL_Debug = 3
    }; 

    // The log file creating rule.
    enum FileCreateRule
    {
        // Add date info to file name.
        // Every date have a log file. 
        kFCR_Date = 0,
        
        // The max size of file is fixed.
        kFCR_Fixed = 1
    }; 

public:
    
    /**
     * Singleton Implementation. 
     *
     * Return the default logger of an application. 
     * 
     */
    static Logger& Instance();

    /**
     * Default constructor.
     * 
     */
    Logger();

    /**
     * Constructor.
     * 
     */
    Logger
    (
        const std::string& name
    );
   
    /**
     * Destructor.
     * 
     */
    ~Logger();  

    /**
     * Set log name.
     * 
     */
    void SetLogName
    (
        const std::string& name
    ); 

    /**
     * Set log level of this logger.
     * It is set using user parameters.
     * 
     */
    void SetTraceLevel
    (
        TraceLevel traceLevel
    );

    /**
     * Set rule to create file.
     * 
     */
    void SetFileCreateRule
    (
        FileCreateRule fileRule
    );

    /*
     *	Set the max size of the log file.
     */
    void SetMaxFileSize
    (
        long maxFileSize
    );
    
    /**
     * Add string log message. 
     * 
     */
    void AddLog
    (        
        const std::string& strlog,
        TraceLevel traceLevel = kTL_Info        
    );

private:
    /**
     * Make directory.
     * 
     */
    void MakeDirectory
    (
        const std::string& name
    );

    /*
     *	Create  stream file.
     */
    void CreateStreamFile
    (
        std::ios::openmode openMode
    );

    /*
     *	Apply log rule.
     */
    void ApplyLogRule
    (
        const SYSTEMTIME& st 
    );

private:

    // File name
    std::string fFileName;
    
    // File create rule.
    FileCreateRule fCreateFileRule;
    
    // The log level.
    TraceLevel fTraceLevel;

    // The time when the inner stream file is opened. 
    SYSTEMTIME fStreamOpenedTime;

    // The max size of stream file.
    long fMaxFileSize;

    // The output stream.
    std::fstream fStream;
};

}// end of namespace MCCommon.